(function() {

    var
    $u = juliet.using({
        func : 'juliet.core.func-0.1',
        cookie : 'juliet.core.cookie',
        string : 'juliet.core.string-0.1',
        Observer : 'juliet.core.Observer-0.1'
    }),
    $ = juliet.jQuery;

    var SwfFlashUploaderMediaType = {

        IMAGE : {
            file_types : '*.jpeg;*.jpg;*.gif;*.png',
            file_types_description : 'Изображения',
            file_size_limit : 0
        }

    };

    var PLACEHOLDER_TEMPLATE = '<div class="${wrapper-class}" style="position: absolute; z-index: 100;">'
        + '<span id="${placeholder-id}"></span></div>';

    var SwfFlashUploaderClass = function() {

        /**
         * Current object observer.
         */
        this.observer = juliet.createObject($u('Observer'));

        /**
         * Instance of uploader flash object.
         */
        this.flashObject = null;

        this.inProgress = false;

        this.canCancelUpload = false;

        this.placeholder = null;

        this.getJSessionId = function() {
            return $u('cookie').get('JSESSIONID');
        };

        this.cancelUpload = function() {
            if (!this.canCancelUpload) {
                return false;
            }

            this.canCancelUpload = false;
            this.flashObject.cancelUpload(null, false);

            return true;
        };

        this.applySettings = function(settings, newSettings) {
            var settingName;

            for (settingName in newSettings) {
                settings[settingName] = newSettings[settingName];
            }
        };

        this.fixUploadUrl = function(settings) {
            settings['upload_url'] = settings['upload_url'] + ';jsessionid=' + this.getJSessionId()
                + '?x-requested-with=Flash';
        };

        this.onFileQueuedHandler = function(file) {
            this.flashObject.addFileParam(file.id, 'file-size', file.size);
            this.observer.notify('file-queued', { file : file });

            if (!this.inProgress) {
                this.inProgress = true;
                this.flashObject.startUpload();
                this.observer.notify('queue-start');
            }
        };

        this.onFileQueueErrorHandler = function(file, errorCode, message) {
            if (errorCode == SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT) {
                // Show error.
            }
        };

        this.onUploadProgressHandler = function(file, bytesComplete, totalBytes) {
            var progress = bytesComplete / totalBytes;

            this.canCancelUpload = ((progress > 0.05) && (progress < 0.95));

            if (typeof file.timeRemaining != 'undefined') {
                file.timeRemaining = ((file.timeRemaining > 0) ? file.timeRemaining : 0);
            }

            this.observer.notify('upload-progress', {
                file : file,
                progress : progress,
                bytesComplete : bytesComplete,
                totalBytes : totalBytes
            });
        };

        this.onUploadErrorHandler = function(file, errorCode, message) {
            if (errorCode != SWFUpload.UPLOAD_ERROR.FILE_CANCELLED) {
                // Show error.
            }

            this.observer.notify('upload-error', { file : file, errorCode : errorCode, message : message });
        };

        this.onUploadSuccessHandler = function(file, serverData) {
            this.observer.notify('upload-success', { file : file, serverData : serverData });
        };

        this.onUploadCompleteHandler = function() {
            this.observer.notify('upload-complete');

            var stats = this.flashObject.getStats();

            if (stats['files_queued'] > 0) {
                this.flashObject.startUpload();
            } else {
                this.inProgress = false;
                this.observer.notify('queue-complete');
            }
        };

        this.createPlaceholder = function(id) {
            var html = $u('string').format(PLACEHOLDER_TEMPLATE, {
                'wrapper-class' : id + 'Wrapper',
                'placeholder-id' : id
            });

            this.placeholder = $(html);
            $(document.body).append(this.placeholder);
        };

        /**
         * Creates uploader flash object using user's settings.
         */
        this.createFlashObject = function(o) {
            this.createPlaceholder(o.settings.button_placeholder_id);

            var settings = {
				flash_url : '/static/flash/swfupload/swfupload.swf',
                file_post_name : 'file-data',
				file_size_limit : '2000 MB',
				file_types : '*.*',
				file_types_description : 'All files',
				file_upload_limit : 0,
				debug : false,

                button_window_mode : SWFUpload.WINDOW_MODE.TRANSPARENT,
                button_cursor : SWFUpload.CURSOR.HAND,
                button_action : SWFUpload.BUTTON_ACTION.SELECT_FILE,

                file_queued_handler : $u('func').proxy(this.onFileQueuedHandler, this),
                file_queue_error_handler : $u('func').proxy(this.onFileQueueErrorHandler, this),
                upload_progress_handler : $u('func').proxy(this.onUploadProgressHandler, this),
                upload_error_handler : $u('func').proxy(this.onUploadErrorHandler, this),
                upload_success_handler : $u('func').proxy(this.onUploadSuccessHandler, this),
                upload_complete_handler : $u('func').proxy(this.onUploadCompleteHandler, this)
			};

            this.applySettings(settings, o.settings);
            this.applySettings(settings, o.type);
            this.fixUploadUrl(settings);

            this.flashObject = new SWFUpload(settings);
        };

        this.initialize = function(o) {
            this.createFlashObject(o);
        };

    };

    SwfFlashUploaderClass.MediaType = SwfFlashUploaderMediaType;

    juliet.registerModule('juliet.flash', 'SwfFlashUploader', SwfFlashUploaderClass);

})();
